//#define USE_DUNGEONBUDDY_DLL
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CommonBehaviors.Actions;
using Styx;
using Styx.CommonBot;
using Styx.CommonBot.POI;
using Styx.Helpers;
using Styx.Pathing;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using Styx.TreeSharp;
using Action = Styx.TreeSharp.Action;
#if USE_DUNGEONBUDDY_DLL
using Bots.DungeonBuddyDll;
using Bots.DungeonBuddyDll.Profiles;
using Bots.DungeonBuddyDll.Attributes;
using Bots.DungeonBuddyDll.Helpers;

namespace Bots.DungeonBuddyDll.Dungeon_Scripts.Classic
#else
    using Bots.DungeonBuddy.Profiles;
    using Bots.DungeonBuddy.Attributes;
    using Bots.DungeonBuddy.Helpers;
namespace Bots.DungeonBuddy.Dungeon_Scripts.Classic
#endif
{
    public class ZulFarrak : Dungeon
    {
        #region Overrides of Dungeon

        public override uint DungeonId
        {
            get { return 24; }
        }

        public override WoWPoint Entrance
        {
            get { return new WoWPoint(-6790.56, -2890.72, 8.88742); }
        }

        public override WoWPoint ExitLocation
        {
            get { return new WoWPoint(1206.67, 842.04, 8.900352); }
        }

        public override void IncludeTargetsFilter(List<WoWObject> incomingunits, HashSet<WoWObject> outgoingunits)
        {
            foreach (var unit in incomingunits.Select(obj => obj.ToUnit()))
            {
                switch (unit.Entry)
                {
                    case 6017: // Lava Spout Totem
                    case 6066: // Earthgrab Totem
                    case 8179: // Greater Healing Ward
                    case 7785: // Ward of Zum'rah
                        outgoingunits.Add(unit);
                        break;

                    case 8877: // Sandfury Zealot
                    case 7787: // Sandfury Slave
                    case 7788: // Sandfury Drudge
                    case 8876: // Sandfury Acolyte
                        if (unit.Combat)
                            outgoingunits.Add(unit);
                        break;
                }
            }
        }

        public override void WeighTargetsFilter(List<Targeting.TargetPriority> units)
        {
            foreach (var p in units)
            {
                WoWUnit unit = p.Object.ToUnit();
                switch (unit.Entry)
                {
                    case 6017: // Lava Spout Totem
                    case 6066: // Earthgrab Totem
                    case 8179: // Greater Healing Ward
                    case 7785: // Ward of Zum'rah
                    case 7797: // Ruuzlu
                        p.Score += 500;
                        break;
                }
            }
        }

        #endregion

        private static readonly WoWPoint FinalBlyLocation = new WoWPoint(1885.295, 1202.984, 8.877242);

        private LocalPlayer Me
        {
            get { return StyxWoW.Me; }
        }


        private WoWGameObject TrollCage
        {
            get { return ObjectManager.GetObjectsOfType<WoWGameObject>().Where(o => o.Entry == 141071).OrderBy(o => o.DistanceSqr).FirstOrDefault(); }
        }

        private WoWUnit SergeantBly
        {
            get { return ObjectManager.GetObjectsOfType<WoWUnit>().FirstOrDefault(o => o.Entry == 7604); }
        }

        private WoWUnit Gahzrilla
        {
            get { return ObjectManager.GetObjectsOfType<WoWUnit>().FirstOrDefault(o => o.Entry == 7273); }
        }

        #region Root

        [EncounterHandler(40712, "Mazoga's Spirit", Mode = CallBehaviorMode.Proximity, BossRange = 45)]
        public Composite QuestPickupHandler()
        {
            WoWUnit unit = null;
            return new PrioritySelector(
                ctx => unit = ctx as WoWUnit,
                new Decorator(
                    ctx => !Me.Combat && !ScriptHelpers.WillPullAggroAtLocation(unit.Location) && unit.QuestGiverStatus == QuestGiverStatus.Available,
                    ScriptHelpers.CreatePickupQuest(() => unit)),
                new Decorator(
                    ctx => !Me.Combat && !ScriptHelpers.WillPullAggroAtLocation(unit.Location) && unit.QuestGiverStatus == QuestGiverStatus.TurnIn,
                    ScriptHelpers.CreateTurninQuest(() => unit)));
        }

        #endregion

        #region Theka the Martyr

        [EncounterHandler(7272, "Theka the Martyr")]
        public Composite ThekaTheMartyrFight()
        {
            const int feveredPlagueId = 8600;
            WoWUnit boss = null;
            return new PrioritySelector(
                ctx => boss = ctx as WoWUnit,
                ScriptHelpers.CreateInterruptCast(() => boss, feveredPlagueId),
                ScriptHelpers.CreateDispellParty("Fevered Plague", ScriptHelpers.PartyDispellType.Curse));
        }

        #endregion

        #region Witch Doctor Zum'rah

        [EncounterHandler(7271, "Witch Doctor Zum'rah")]
        public Composite WitchDoctorZumrahFight()
        {
            const int shadowboltVolley = 15245;
            const int healingWave = 12491;
            WoWUnit boss = null;
            return new PrioritySelector(ctx => boss = ctx as WoWUnit, ScriptHelpers.CreateInterruptCast(() => boss, shadowboltVolley, healingWave));
        }

        #endregion

        #region Nekrum Gutchewer

        [EncounterHandler(7796, "Nekrum Gutchewer")]
        public Composite NekrumGutchewerFight()
        {
            const int feveredPlagueId = 15245;
            WoWUnit boss = null;
            return new PrioritySelector(
                ctx => boss = ctx as WoWUnit,
                ScriptHelpers.CreateInterruptCast(() => boss, feveredPlagueId),
                ScriptHelpers.CreateDispellEnemy("Renew", ScriptHelpers.EnemyDispellType.Magic, () => boss));
        }

        #endregion

        #region Hydromancer Velratha

        [EncounterHandler(7795, "Hydromancer Velratha")]
        public Composite HydromancerVelrathaFight()
        {
            const int healingWaveId = 12491;
            WoWUnit boss = null;
            return new PrioritySelector(ctx => boss = ctx as WoWUnit, ScriptHelpers.CreateInterruptCast(() => boss, healingWaveId));
        }

        #endregion

        #region Gahz'rilla

        private const uint GahzrillId = 7273;

        [ObjectHandler(141832, "Gong of Zul'Farrak", 100)]
        public Composite GongHandler()
        {
            WoWGameObject gong = null;
            return new PrioritySelector(
                ctx => gong = ctx as WoWGameObject,
                new Decorator(
                    ctx => BossManager.CurrentBoss != null && BossManager.CurrentBoss.Entry == GahzrillId,
                    new PrioritySelector(
                        new Decorator(
                            ctx =>
                            ScriptHelpers.GetUnfriendlyNpsAtLocation(() => gong.Location, 100, u => u.IsHostile).Any() && Targeting.Instance.IsEmpty() &&
                            BotPoi.Current.Type == PoiType.None,
                            ScriptHelpers.CreateClearArea(() => gong.Location, 100, u => u.IsHostile)),
                        new Decorator(
                            ctx =>
                            ScriptHelpers.IsBossAlive("Gahz'rilla") && Me.IsTank() && Targeting.Instance.IsEmpty() && Gahzrilla == null && BotPoi.Current.Type == PoiType.None &&
                            !ScriptHelpers.GetUnfriendlyNpsAtLocation(() => gong.Location, 100, u => u.IsHostile).Any(),
                            new PrioritySelector(
                                ctx => gong = ctx as WoWGameObject,
                                new ActionSetActivity("Interacting with {0}", gong),
                                new Decorator(ctx => gong != null && gong.DistanceSqr > 4 * 4, new Action(ctx => Navigator.MoveTo(gong.Location))),
                                new Decorator(ctx => gong != null && gong.DistanceSqr <= 4 * 4, new Sequence(new Action(ctx => gong.Interact()))))))));
        }

        [EncounterHandler(7273, "Gahz'rilla")]
        public Composite GahzrillaFight()
        {
            WoWUnit boss = null;
            return new PrioritySelector(ctx => boss = ctx as WoWUnit, ScriptHelpers.CreateDispellParty("Freeze Solid", ScriptHelpers.PartyDispellType.Magic));
        }

        #endregion

        #region Shadowpriest Sezz'ziz

        [EncounterHandler(7275, "Shadowpriest Sezz'ziz")]
        public Composite ShadowpriestSezzzizFight()
        {
            const int healId = 12039;
            const int renewId = 8362;
            WoWUnit boss = null;
            return new PrioritySelector(
                ctx => boss = ctx as WoWUnit,
                ScriptHelpers.CreateInterruptCast(() => boss, healId, renewId),
                ScriptHelpers.CreateDispellEnemy("Renew", ScriptHelpers.EnemyDispellType.Magic, () => boss));
        }

        #endregion

        #region Chief Ukorz Sandscalp

        [EncounterHandler(7275, "Chief Ukorz Sandscalp")]
        [EncounterHandler(7797, "Ruuzlu")]
        public Composite ChiefUkorzSandscalpFight()
        {
            WoWUnit boss = null;
            return new PrioritySelector(
                ctx => boss = ctx as WoWUnit,
                ScriptHelpers.CreateAvoidUnitAnglesBehavior(ctx => !Me.IsTank() && boss.Distance < 8, () => boss, new ScriptHelpers.AngleSpan(0, 189)),
                ScriptHelpers.CreateTankFaceAwayGroupUnit(() => boss, 8));
        }

        #endregion

        [ObjectHandler(146084, "End Door", 180)]
        public Composite PrisonerEvent()
        {
            WoWGameObject endDoor = null;
            WoWGameObject trollCage = null;
            WoWUnit sergeantBly = null;

            return new PrioritySelector(
                ctx => endDoor = ctx as WoWGameObject,
                new Decorator(
                    ctx => endDoor.State != WoWGameObjectState.Active && endDoor.State != WoWGameObjectState.ActiveAlternative && StyxWoW.Me == ScriptHelpers.Tank,
                // context switch to troll cage
                    new PrioritySelector(
                        ctx => trollCage = TrollCage,
                // cages are closed, lets go open them.
                        new Decorator(
                            ctx => trollCage != null && trollCage.State == WoWGameObjectState.Ready,
                            new PrioritySelector(
                                new Decorator(ctx => trollCage.DistanceSqr > 4 * 4, new Action(ctx => ScriptHelpers.MoveTankTo(trollCage.Location))),
                                new Decorator(ctx => trollCage.DistanceSqr <= 4 * 4, ScriptHelpers.CreateInteractWithObject(141071)))),
                // cages are open lets help the prisoners fight off the waves of NPCs
                        new Decorator(
                            ctx => trollCage != null && trollCage.State == WoWGameObjectState.Active,
                // context switch to sergent bly,
                            new PrioritySelector(
                                ctx => sergeantBly = SergeantBly,
                                new Decorator(
                                    ctx => sergeantBly != null && Targeting.Instance.IsEmpty() && sergeantBly.CanGossip &&  sergeantBly.Location.DistanceSqr(FinalBlyLocation) < 7,
                                    ScriptHelpers.CreateTalkToNpc(() => sergeantBly)),
                                new Decorator(
                                    ctx => sergeantBly != null && sergeantBly.IsAlive && sergeantBly.DistanceSqr >= 6 * 6,
                                    new Action(ctx => ScriptHelpers.MoveTankTo(sergeantBly.Location))))),
                        new Decorator(ctx => Targeting.Instance.IsEmpty() && BotPoi.Current.Type == PoiType.None && Me.IsTank(), new ActionAlwaysSucceed()))));
        }
    }
}